home *** CD-ROM | disk | FTP | other *** search
- UNIT LibFile;
-
- INTERFACE
-
- USES Dos,Objects;
-
- TYPE
- PLFDirEntry = ^TLFDirEntry;
- TLFDirEntry =
- RECORD
- name : ARRAY[1..24] OF CHAR;
- offs : LONGINT;
- size : LONGINT;
- END;
-
- VAR
- FicheroExe : STRING;
- header: ARRAY [1..28] OF BYTE;
- handle,PSPSegment,StartSegment:WORD;
- item: ARRAY [1..2] OF WORD;
- memory,imagesize:WORD;
- commandline:STRING[125];
-
- FUNCTION LF_FindFile(FName: STRING) : PLFDirEntry;
- PROCEDURE LF_Free;
- PROCEDURE ExecFile(pos:LONGINT);
-
- IMPLEMENTATION
-
-
- PROCEDURE LF_Init(FName: STRING; VAR Coll: TCollection);
- VAR
- St : TDosStream;
- n, NFiles,
- LastOffset : LONGINT;
- i : INTEGER;
- de : PLFDirEntry;
- LABEL
- Fin;
- BEGIN
- St.Init(Fname, stOpenRead);
- IF St.Status <> stOk THEN EXIT;
-
- St.Seek(St.GetSize-16);
- St.Read(n, 4);
- IF n <> $DF73B489 THEN GOTO Fin;
- St.Read(NFiles, 4);
- St.Read(n, 4);
- St.Read(LastOffset, 4);
-
- LastOffset := St.GetSize-LastOffset;
- St.Seek(LastOffset);
-
- FOR i := 1 TO NFiles DO
- BEGIN
- NEW(de);
- St.Read(de^, SIZEOF(de^));
- de^.offs := LastOffset - de^.offs;
- Coll.Insert(de);
- END;
-
- Fin:
- St.Done;
- END;
-
- VAR
- LF_Coll : TCollection;
-
- FUNCTION CmpName(VAR _p1; p2: STRING) : BOOLEAN;
- VAR
- p1 : ARRAY[1..24] OF CHAR ABSOLUTE _p1;
- i : INTEGER;
- BEGIN
- CmpName := FALSE;
- FOR i := 1 TO Length(p2) DO
- IF p1[i] <> p2[i] THEN EXIT;
- CmpName := TRUE;
- END;
-
- FUNCTION LF_FindFile(FName: STRING) : PLFDirEntry;
- VAR
- i : INTEGER;
- de : PLFDirEntry;
- BEGIN
- LF_FindFile := NIL;
- FOR i := 1 TO Length(FName) DO
- FName[i] := UpCase(FName[i]);
- FOR i := 0 TO LF_Coll.Count - 1 DO
- BEGIN
- de := LF_Coll.At(i);
- IF CmpName(de^.name, FName) THEN
- BEGIN
- LF_FindFile := de;
- EXIT;
- END;
- END;
- END;
-
- PROCEDURE LF_Free;
- VAR
- i : INTEGER;
- de : PLFDirEntry;
- BEGIN
- FOR i := LF_Coll.Count - 1 DOWNTO 0 DO
- BEGIN
- de := LF_Coll.At(i);
- Dispose(de);
- END;
- LF_Coll.DeleteAll;
- LF_Coll.Done;
- END;
-
- { }
- { convierte un string en formato ASCIIZ para utilizarlo con }
- { las funciones del DOS }
- { }
-
- PROCEDURE StringToAsciiz; ASSEMBLER;
- ASM
- mov bx,OFFSET FicheroExe
- xor cx,cx
- mov cl,[bx]
- @@StringToASCII:
- mov al,[bx+1]
- mov [bx],al
- inc bx
- loop @@StringToASCII
- mov byte ptr [bx],0
- END;
-
- { }
- { Carga, reubica y ejecuta un fichero .EXE }
- { Versión 2.11 }
- { }
-
- PROCEDURE ExecFile(pos:LONGINT); ASSEMBLER;
- ASM
- push es
- call StringToAsciiz { convierte el nombre del .exe a ASCIIZ }
-
- {------------------}
-
- push ds
- mov ax,3d00h
- mov dx,OFFSET FicheroExe
- int 21h { abre el fichero para sólo lectura }
-
- { indexado del fichero }
-
- push ax
- mov bx,ax { handle del fichero }
- mov ax,04200h
- mov dx,word ptr [pos]
- mov cx,word ptr [pos+2]
- int 21h
- pop ax
-
- mov [handle],ax { guarda el handle del fichero }
- mov bx,[handle]
- mov dx,OFFSET header { cabecera del fichero .exe }
- mov cx,28
- mov ah,3fh
- int 21h { lee los 28 bytes estándar de la cabecera }
- pop ds
-
- {-------------------}
-
- mov bx,OFFSET header
- mov cx,[bx+08h] { longitud del header en parágrafos }
- mov ax,16
- imul cx { DX:AX -> posición de inicio de módulo }
- mov cx,dx
- mov dx,ax { CX:DX -> posición para el LSEEK }
- add dx,word ptr [pos]
- adc cx,word ptr [pos+2]
- mov bx,[handle]
- xor al,al
- mov ah,42h
- int 21h { posiciona el puntero del fichero al }
- { inicio del modulo del programa }
-
- {--------------------}
-
- mov bx,OFFSET header
- mov ax,[bx+4] { longitud total incluyendo la cabecera }
- inc ax { 1+ por si acaso }
- mov cx,32
- mul cx { parágrafos totales }
- mov [imagesize],ax { tamaño del modulo del programa }
-
- {--------------------}
-
- { Calcula los nuevos parámetros mínimo y máximo para ejecutar el programa }
- mov ax,[imagesize]
- add ax,16 { Para el PSP }
- cmp ax,WORD PTR header[0Ah]
- jbe @@MinOk
- mov WORD PTR header[0Ah],ax
- @@MinOk:
- cmp ax,WORD PTR header[0Ch]
- jbe @@MaxOk
- mov WORD PTR header[0Ch],ax
- @@MaxOk:
-
- {--------------------}
-
- mov bx,WORD PTR header[0Ch]
- mov [memory],bx
- mov ah,48h
- int 21h
- jnc @@no_error0
- cmp bx,WORD PTR header[0Ah]
- jb @@NoHayMem
- mov [memory],bx
- mov ah,48h
- int 21h { con esto reservamos el máximo de memoria }
- @@no_error0:
- mov [PSPSegment],ax
-
- { genera un nuevo PSP...UNDOCUMENTED! }
-
- push ax
- mov dx,ax
- mov ah,055h
- mov si,dx
- add si,10h
- add si,[memory] { valor a escribir en el campo de memoria }
- int 21h { del PSP }
- pop ax
-
- mov es,ax
- xor di,di
- mov word ptr es:[di+0ah],OFFSET @@retorna
- mov es:[di+0ch],cs
-
- add ax,16
- mov [StartSegment],ax
-
- {----------------------}
-
- { aquí nos encargamos de leer el módulo principal del programa, que }
- { no es más que el código y los datos en sí... }
-
- mov bx,[handle]
- mov cx,[imagesize]
- push ds
- mov ds,[StartSegment]
- @@next_block:
- push cx
- xor dx,dx
- mov cx,16 { 16 bytes cada bloque }
- mov ah,3fh
- xor al,al
- int 21h
- jc @@end_read
- mov ax,ds
- inc ax
- mov ds,ax
- pop cx
- loop @@next_block
- pop ds
- jmp @@readgood
- @@end_read:
- pop cx
- pop ds
- @@readgood:
-
- {-----------------------}
-
- { ahora posiciona el puntero del fichero al inicio de la tabla de }
- { reubicación del fichero .EXE }
-
- mov si,OFFSET header
- mov ax,[si+18h] { offset en bytes en el fichero de la tabla de }
- mov dx,ax { reubicación del .exe }
- xor cx,cx
- add dx,word ptr [pos] { más la posición }
- adc cx,word ptr [pos+2]
- mov bx,[handle]
- mov ah,42h
- xor al,al
- int 21h
-
- {------------------------}
-
- { ahora comienza la reubicación de verdad del fichero }
-
- mov si,OFFSET header
- mov cx,[si+06h] { número de datos de items de la tabla de reubicación }
- test cx,0ffffh
- jz @@no_realocate
- @@siguiente_item:
- push cx
- mov dx,OFFSET item
- mov bx,[handle]
- mov cx,4 { cada item se compone de offset:segmento -> 4 bytes }
- mov ah,3fh
- int 21h
- mov bx,OFFSET item
- mov ax,[StartSegment] { a cada posición indicada por el item se }
- add ax,[bx+2] { le suma el segmento de inicio del modulo }
- mov di,[bx]
- mov es,ax
- mov ax,es:[di]
- add ax,[StartSegment]
- mov es:[di],ax
- pop cx
- loop @@siguiente_item
- @@no_realocate:
-
- {-------------------------}
-
- mov bx,[handle]
- mov ah,3eh
- int 21h { cierra el fichero }
-
- { set new PSP address...UNDOCUMENTED! }
-
- mov bx,[PSPSegment]
- mov ah,50h
- int 21h
-
- {-------------------------}
-
- { ahora le pasa la línea de comandos }
-
- push es
- mov es,[PSPSegment]
- mov di,080h
- mov bx,OFFSET commandline
- mov cl,[bx]
- xor ch,ch
- mov es:[di],cl
- inc bx
- inc di
- test cx,0ffffh
- jz @@ignora_com
- @@next_com:
- mov al,[bx]
- mov es:[di],al
- inc bx
- inc di
- loop @@next_com
- @@ignora_com:
- mov byte ptr es:[di],0dh
- mov byte ptr es:[di+1],0
- pop es
-
- {-------------------------}
-
- mov bx,OFFSET @@oldss
-
- cli
- mov cs:[bx],ss
- mov cs:[bx+2],sp
- mov cs:[bx+4],bp
- sti
-
- mov bx,OFFSET header
- mov ax,[bx+0eh]
- add ax,[StartSegment]
-
- cli
- mov ss,ax
- mov sp,[bx+10h] { genera SS:SP a partir del header }
- sti
-
- mov ax,[bx+14h]
- mov dx,[bx+16h]
- add dx,[StartSegment] { DX:AX -> CS:IP }
- push dx
- push ax
-
- mov es,[PSPSegment]
- mov ds,[PSPSegment]
-
- xor ax,ax { borra todos los registros }
- mov di,ax
- mov si,ax
- mov bx,ax
- mov cx,ax
- mov dx,ax
- mov bp,ax
-
- retf
- @@retorna:
- mov bx,OFFSET @@oldss
- cli
- mov ss,cs:[bx] { recupera todos los registros }
- mov sp,cs:[bx+2]
- mov bp,cs:[bx+4]
- sti
- mov ax,SEG @data
- mov ds,ax
-
- {-----------------------}
-
- mov es,[PSPSegment]
- mov ah,49h
- int 21h { libera la memoria guardada por el }
-
- {-----------------------}
-
- jmp @@restore
-
- @@oldss: dw 0
- @@oldsp: dw 0
- @@oldbp: dw 0
-
- @@NoHayMem:
- mov bx,[handle]
- mov ah,3eh
- int 21h { cierra el fichero }
- @@restore:
- pop es
- END;
-
- BEGIN
-
- LF_Coll.Init(10, 10);
-
- LF_Init('pump.exe', LF_Coll);
- {LF_Init(ParamStr(0), LF_Coll);}
-
- END.
-